package be.jaisy.project.service.impl;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;

import be.jaisy.osgi.exception.OSGIBusinessException;
import be.jaisy.osgi.transaction.AbstractTransactionnalService;
import be.jaisy.osgi.transaction.TransactionCallback;
import be.jaisy.osgi.transaction.TransactionCallbackWithoutResult;
import be.jaisy.osgi.transaction.TransactionStatus;
import be.jaisy.project.adapter.IProjectDao;
import be.jaisy.project.adapter.domain.Project;
import be.jaisy.project.service.api.IProjectService;
import be.jaisy.project.service.api.to.ProjectTo;

public class ProjectServiceImpl extends AbstractTransactionnalService implements IProjectService, Serializable {

	private static final long serialVersionUID = -2013023554616442857L;

	private IProjectDao projectDao;

	public void setProjectDao(IProjectDao projectDao) {
		this.projectDao = projectDao;
	}

	public void unSetProjectDao(IProjectDao projectDao) {
		this.projectDao = null;
	}

	@SuppressWarnings("unchecked")
	public Collection listProject() {
		Collection<ProjectTo> projectTos = (Collection<ProjectTo>)getTransactionTemplate().execute(new TransactionCallback(){

			public Collection<ProjectTo> doInTransaction(TransactionStatus status) {
				return convert(projectDao.findAll());
			}});		
		return projectTos;
	}
	
	public void createProject(final ProjectTo projectTo) {
		if (this.projectDao == null)
			throw new IllegalStateException("Service " + IProjectDao.class.getName() + " not registered");

		getTransactionTemplate().execute(new TransactionCallbackWithoutResult(){

			public void doInTransactionWithoutResult(TransactionStatus status) {
				projectDao.makePersistent(convertTo(projectTo));				
			}});
	}

	public void deleteProject(final ProjectTo projectTo) {
		if (this.projectDao == null)
			throw new IllegalStateException("Service " + IProjectDao.class.getName() + " not registered");

		getTransactionTemplate().execute(new TransactionCallbackWithoutResult(){

			public void doInTransactionWithoutResult(TransactionStatus status) {
				
				Project project = projectDao.findByName(projectTo.getName(), true);
				if(project==null)
					throw new OSGIBusinessException("Cannot delete non existing project with name ["+projectTo.getName()+"]");
				projectDao.makeTransient(project);				
			}});
		
	}

	public ProjectTo getProject(final String name) {
		if (this.projectDao == null)
			throw new IllegalStateException("Service " + IProjectDao.class.getName() + " not registered");
		
		ProjectTo projectTo = (ProjectTo)getTransactionTemplate().execute(new TransactionCallback(){

			public ProjectTo doInTransaction(TransactionStatus status) {
				return convert(projectDao.findByName(name, false));
			}});		
		return projectTo;
	}

	public void updateProject(final ProjectTo projectTo) {
		if (this.projectDao == null)
			throw new IllegalStateException("Service " + IProjectDao.class.getName() + " not registered");

		getTransactionTemplate().execute(new TransactionCallbackWithoutResult(){

			public void doInTransactionWithoutResult(TransactionStatus status) {
				Project project = projectDao.findByName(projectTo.getName(), true);
				if(project==null)
					throw new OSGIBusinessException("Cannot update non existing project with name ["+projectTo.getName()+"]");
				project.setDescription(projectTo.getDescription());
				projectDao.makePersistent(project);							
			}});
		
	}
	
	public static Collection<Project> convertTo(Collection<ProjectTo> projectTos){
		if(projectTos==null)
			return null;
		Collection<Project> projects = new ArrayList<Project>(projectTos.size());
		for (ProjectTo projectTo : projectTos) {
			projects.add(convertTo(projectTo));
		}
		return projects;
	}
	
	public static Project convertTo(ProjectTo projectTo){
		if(projectTo==null)
			return null;
		Project project = new Project();
		project.setName(projectTo.getName());
		project.setDescription(projectTo.getDescription());
		return project;
	}
	
	public static Collection<ProjectTo> convert(Collection<Project> projects){
		if(projects==null)
			return null;
		Collection<ProjectTo> projectTos = new ArrayList<ProjectTo>(projects.size());
		for (Project project : projects) {
			projectTos.add(convert(project));
		}
		return projectTos;
	}
	
	public static ProjectTo convert(Project project){
		if(project==null)
			return null;
		ProjectTo projectTo = new ProjectTo();
		projectTo.setName(project.getName());
		projectTo.setDescription(project.getDescription());
		return projectTo;
	}
	
}
